<?php

namespace App\Models;


class SaoPay extends BaseModel
{

    protected $table = "saopay";

    protected $redisTable = "saopay";

    //接口
//    const BASE_URL = 'http://saobei.lcsw.cn/lcsw/';
    const BASE_URL = 'https://pay.lcsw.cn/lcsw/';
    //010微信，020 支付宝，060qq钱包，080京东钱包，090口碑，100翼支付，110银联二维码，000自动识别类型
    private $pay_type = ['010', '020', '060', '080', '090', '100'];

    private $service_id = ['090', '010', '011', '012', '015', '020'];

    private $pay_ver = 100;


    protected $rules = [
        'shop_id' => 'required|unique:saopay,shop_id',
        'merchant_no' => 'required',
        'terminal_id' => 'required',
        'token' => 'required',
    ];

    protected $message = [
        'shop_id.required' => '非法操作',
        'merchant_no.required' => '请填写商户号',
        'terminal_id.required' => '请填写终端号',
        'token.required' => '请填写令牌',
    ];

    public function shop()
    {
        return $this->hasOne('App\Models\Shop', 'id', 'shop_id');
    }

    public function getOpenId($sid,$mid)
    {
        $saopaySet = $this->_redisGetOneBySid($sid);
        $redirectUrl = url('authopenid',['mid'=>$mid]);
        $data = [
            'merchant_no' => $saopaySet['merchant_no'],
            'redirect_uri' => $redirectUrl,
            'terminal_no' => $saopaySet['terminal_id'],

        ];
        $redirectUrl = urlEncode($redirectUrl);
        $data = $this->generateParams($data, $saopaySet['token']);
        $url = self::BASE_URL . 'wx/jsapi/authopenid?' . "merchant_no={$saopaySet['merchant_no']}&redirect_uri={$redirectUrl}&terminal_no={$saopaySet['terminal_id']}&key_sign={$data['key_sign']}";
        $this->https_request($url, [], 30, ['Content-Type: application/json']);
    }


    public function prepay($xcx_openid, $wx_openid, $orderInfo, $openid, $type = 1)
    {
        $openid = $openid ? $openid : $wx_openid ? $wx_openid : $xcx_openid;
        $payType = $wx_openid ? 'jspay' : 'minipay';
        $name = $type == 1 ? '订单' : '水票';
        $notify_url = $type == 1 ? urlHome('order', 'anyPayNotify') : urlHome('waterBill', 'anyPayNotify');
        $saopaySet = $this->_redisGetOneBySid($orderInfo['shop_id']);
        if (!$saopaySet) {
            $this->error = '该商户未配置微信支付';
            return false;
        }
        $payArr = [
            'jspay' => [
                'api' => "pay/{$this->pay_ver}/jspay",
                'service_id' => '012'
            ],
            'minipay' => [
                'api' => "pay/{$this->pay_ver}/minipay",
                'service_id' => '015'
            ],
        ];
        $url = self::BASE_URL . $payArr[$payType]['api'];
        $data = [
            'pay_ver' => $this->pay_ver,
            'pay_type' => '010',
            'service_id' => $payArr[$payType]['service_id'],
            'merchant_no' => $saopaySet['merchant_no'],
            'terminal_id' => $saopaySet['terminal_id'],
            'terminal_trace' => $orderInfo['order_sn'],
            'terminal_time' => date('YmdHis', $orderInfo['addtime']),
            'total_fee' => $orderInfo['order_amount'] * 100,
        ];
        $data = $this->generateParams($data, $saopaySet['token']);
        $arr = [
            'open_id' => $openid,
            'order_body' => $name . '编号:' . $orderInfo['order_sn'],
            'notify_url' => $notify_url,
            'attach' => $orderInfo['shop_id'],
//            'goods_detail' => '',
        ];
        $data = array_merge($data, $arr);
//        dd($data);
        $header = ['Content-Type: application/json'];
        $res = $this->https_request($url, $data, 30, $header);
        if (!$res) {
            $this->error = '获取微信支付统一下单信息失败';
            return false;
        }
        if (!($res['return_code'] == '01' && $res['result_code'] == '01')) {
            $this->error = $res['return_msg'];
            return false;
        }
        //组合支付参数
        $resData = [
            'appId' => strval($res['appId']),
            'timeStamp' => strval($res['timeStamp']),
            'nonceStr' => strval($res['nonceStr']),
            'package' => strval($res['package_str']),
            'signType' => strval($res['signType']),
            'paySign' => strval($res['paySign'])
        ];
        return $resData;
    }


    /**
     * @return array|bool
     * 扫呗微信支付回调验证
     * 返回数据
     * $type:1零售支付  2.购买水票  3.店铺续费
     */
    public function notify($type = 1)
    {
        $data = file_get_contents('php://input');
        if (!$data) {
            return false;
        }
        $data = json_decode($data, true);
        if (empty($data)) {
            return false;
        }
        $data_sign = $data['key_sign'];
        $signParams = [
            'return_code' => $data['return_code'],
            'return_msg' => $data['return_msg'],
            'result_code' => $data['result_code'],
            'pay_type' => $data['pay_type'],
            'user_id' => $data['user_id'],
            'merchant_name' => $data['merchant_name'],
            'merchant_no' => $data['merchant_no'],
            'terminal_id' => $data['terminal_id'],
            'terminal_trace' => $data['terminal_trace'],
            'terminal_time' => $data['terminal_time'],
            'total_fee' => $data['total_fee'],
            'end_time' => $data['end_time'],
            'out_trade_no' => $data['out_trade_no'],
            'channel_trade_no' => $data['channel_trade_no'],
            'attach' => $data['attach']
        ];
        $saopaySet = $this->_redisGetOneBySid($data['attach']);
        $params = $this->generateParams($signParams, $saopaySet['token']);
        if (($params['key_sign'] === $data_sign) && ($params['return_code'] == '01') && ($params['result_code'] == '01')) {
            $dealResult = false;
            $model = '';
            if ($type == 1) {
                $model = new Order();
            }
            if ($type == 2) {
                $model = new WaterBillOrder();
            }
            if ($type == 3) {
                $model = new ServiceCharge();
            }
            if ($model) {
                $dealResult = $model->dealOrder($data['terminal_trace']);
                tolog('dealResult: ' . ($dealResult ? 'yes' : 'no'));
                tolog('error: ' . $model->getError());
            }
            if ($dealResult) {
                echo json_encode(['return_code' => '01', 'return_msg' => 'success']);
                exit;
            } else {
                if ($model && $model->getError()) {
                    $notifyLog = new NotifyLog();
                    $notifyLog->add($type, $data, $model->getError());
                    $model->dealOrder($data['terminal_trace']);
                }
            }
        }
    }


    public function generateParams($param, $accessToken = '')
    {
        $buff = "";
        foreach ($param as $k => $v) {
            if ($k != "sign") {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        if ($accessToken) {
            $buff .= "&access_token=$accessToken";
        }
        $param['key_sign'] = md5($buff);
        return $param;
    }

    public function addOrUpdate()
    {
        $data['shop_id'] = intval(request('shop_id'));
        $data['merchant_no'] = trim(request('merchant_no'));
        $data['terminal_id'] = trim(request('terminal_id'));
        $data['token'] = trim(request('token'));
        if (request('id')) {
            $data['id'] = trim(request('id'));
            $this->rules['shop_id'] .= ',' . $data['id']; //唯一字段验证,在更新时排除当前id
        }
        if (!$this->_validate($data)) {
            return false;
        }
        $res = $this->_save($data);
        if (!$res) {
            $this->error = '保存失败!';
            return false;
        }
        $this->_redisGenerate($data['shop_id']);
        //记录行为
        return $res;
    }

    public function _redisGenerate($sid)
    {
        $table = $this->redisTable;
        $key = $sid;
        $this->redis->hdel($table, $key);
    }


    public function _redisGetOneBySid($sid)
    {
        $table = $this->redisTable;
        $key = $sid;
        if ($this->redis->hexists($table, $key)) {
            $res = $this->redis->hmget($table, $key);
            if ($res) {
                return unserialize($res[0]);
            }
        }
        $res = $this->_getOne(['shop_id' => $sid]);
        if ($res) {
            $res = $res->toArray();
            $this->redis->hmset($table, [$key => serialize($res)]);
        }
        return $res;
    }


    public function https_request($url, $data = [], $second = 30, $aHeader = [])
    {
        $ch = curl_init();
        //超时时间
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        if (count($aHeader) >= 1) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
        }
        if (!empty($data)) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
//    dd(json_encode($data));
        $data = curl_exec($ch);
//    dd($data);
        if ($data) {
            curl_close($ch);
            return json_decode($data, true);
        } else {
            $error = curl_errno($ch);
            echo "call faild, errorCode:$error\n";
            curl_close($ch);
            return false;
        }
    }


}
